use super::c::{context, UrstBindMem};
use super::cpblock::CPBlock;
use super::handle::{is_void_null, Handle};
use fnv::FnvHashMap;
use std::ffi::CString;
use std::string::String;

#[derive(Clone, Default, Debug)]
pub struct Context {
    handle: Handle,
    blocks: FnvHashMap<String, CPBlock>,
}

impl Context {
    pub fn new(dir: CString) -> Self {
        unsafe {
            let handle = context(dir.as_ptr() as *const u8);
            Self {
                handle: Handle::new(handle),
                blocks: FnvHashMap::default(),
            }
        }
    }
    pub fn bind(self: &mut Self, name: CString) -> CPBlock {
        let file_name = name.clone().into_string().ok().unwrap();
        match self.blocks.get(&file_name) {
            Some(m) => (*m).clone(),
            None => unsafe {
                match self.handle.h {
                    Some(h) => unsafe {
                        let mem = UrstBindMem(h, name.as_ptr() as *const u8);
                        if !is_void_null(mem) {
                            self.blocks.insert(file_name, CPBlock::new(mem));
                        }
                        CPBlock::new(mem)
                    },
                    None => CPBlock::default(),
                }
            },
        }
    }
}

#[cfg(test)]
#[test]
fn test_context() {
    let tmpdir = CString::new("/tmp/usrtos").unwrap();
    let mut ctx = Context::new(tmpdir);

    let mem = ctx.bind(CString::new("log0").unwrap());
    match mem.cpblock.h {
        Some(_c) => println!("log0"),
        None => println!("None"),
    }
}
